#include "debug.h"

#include <nds.h>
#include "container_riff.h"

// ------------------------
bool ContainerRIFF::init(std::string filepath)
// ------------------------
{
	reader.init(filepath);
	
	// read and check for RIFF chunk
	char ch[4];

	if (!reader.read_byte_block((uint8_t *)&ch, 4, true)) return false;
	chData.ckID.assign(ch, 4);
	if (chData.ckID.compare(0, 4, "RIFF") != 0) return false;

	chData.ckStart = 12;
	chData.ckSize = 0;
	chData.ckPos = 0;
	
	if (!reader.read_uint32_le(&riffSize, 32)) return false;
	if (!reader.read_byte_block((uint8_t *)&ch, 4, true)) return false;
	chData.ckType.assign(ch, 4);

	return true;
}

// ------------------------
void ContainerRIFF::rewind()
// ------------------------
{
	reader.seek(12);
	chData.ckStart = 12;
	chData.ckSize = 0;
	chData.ckPos = 0;
}

// ------------------------
bool ContainerRIFF::nextChunk()
// ------------------------
{
	// calculate next chunk's starting point
	chData.ckStart = chData.ckStart + chData.ckSize + 8;
	
	// fail if start position exceeds the RIFF chunk (EOF)
	if (chData.ckStart > 8+riffSize)
	{
		#ifdef DEBUG_CONT_RIFF
		iprintf("ckStart (%u) > 8+riffSize (%u)\n", chData.ckStart, riffSize);
		#endif
		return false;
	}
	
	// seek to that point
	reader.seek(chData.ckStart-8);
	// read header
	char tmp[4];
	if (!reader.read_byte_block((uint8_t *)tmp, 4, true))
	{
		#ifdef DEBUG_CONT_RIFF
		iprintf("reader fail 1\n");
		#endif
		return false;
	}
		
	// store header
	chData.ckID.assign(tmp, 4);
	chData.ckPos = 0;
	if (!reader.read_uint32_le(&chData.ckSize, 32))
	{
		#ifdef DEBUG_CONT_RIFF
		iprintf("reader fail 2\n");
		#endif
		return false;
	}
	chData.ckType.clear();
	
	// check for LIST type
	if (chData.ckID.compare(0, 4, "LIST") == 0)
	{
		if (!reader.read_byte_block((uint8_t *)tmp, 4, true))
		{
			#ifdef DEBUG_CONT_RIFF
			iprintf("reader fail 2\n");
			#endif
			return false;
		}
		chData.ckType.assign(tmp, 4);
		subchData.ckStart = chData.ckStart + 4;
		chData.ckPos = 4;
		subchData.ckSize = 0;
	}

	#ifdef DEBUG_CONT_RIFF
	iprintf("ckID:%s\n", chData.ckID.data());
	iprintf("ckSize:%u\n", chData.ckSize);
	iprintf("ckType:%s\n", chData.ckType.data());
	#endif

	return true;
}

// ------------------------
ContainerRIFFChunk ContainerRIFF::getChunkHead()
// ------------------------
{
	return chData;
}

// ------------------------
void ContainerRIFF::readChunkData(char *data, uint32_t len)
// ------------------------
{
	uint32_t tmp = (((chData.ckSize - chData.ckPos) < len) ? (chData.ckSize - chData.ckPos) : len);
	reader.read_byte_block((uint8_t *)data, tmp, true);
	chData.ckPos += tmp;
}

// ------------------------
uint32_t ContainerRIFF::getChunkRemLen()
// ------------------------
{
	#ifdef DEBUG_CONT_RIFF
	iprintf("ContainerRIFF::getChunkRemLen %d\n", chData.ckSize - chData.ckPos);
	#endif
	if ( reader.eof() )
	{
		#ifdef DEBUG_CONT_RIFF
		iprintf("ContainerRIFF::getChunkRemLen EOF\n");
		#endif
		return 0;
	}
	return chData.ckSize - chData.ckPos;
}

// ------------------------
bool ContainerRIFF::nextSubChunk()
// ------------------------
{
	// calculate next subchunk's starting point
	subchData.ckStart = subchData.ckStart + subchData.ckSize + 8;
	
	// fail if start position exceeds the LIST chunk
	if (subchData.ckStart > chData.ckStart + chData.ckSize) return false;
	
	// seek to that point
	reader.seek(subchData.ckStart-8);

	// read header
	char tmp[4];
	if (!reader.read_byte_block((uint8_t *)tmp, 4, true)) return false;

	subchData.ckID.assign(tmp, 4);
	subchData.ckPos = 0;

	if (!reader.read_uint32_le(&subchData.ckSize, 32)) return false;
	subchData.ckType.clear();
	
	return true;
}

// ------------------------
ContainerRIFFChunk ContainerRIFF::getSubChunkHead()
// ------------------------
{
	return subchData;
}

// ------------------------
void ContainerRIFF::readSubChunkData(char *data, uint32_t len)
// ------------------------
{
	uint32_t tmp = (((subchData.ckSize - subchData.ckPos) < len) ? (subchData.ckSize - subchData.ckPos) : len);
	reader.read_byte_block((uint8_t *)data, tmp, true);
	subchData.ckPos += tmp;
	chData.ckPos += tmp;
}

